Skip to content

fix(uuid): unbreak compliance ratchet and match google/uuid leniency - #196

Merged
sspaink merged 2 commits into
open-policy-agent:mainfrom
sspaink:fix/uuid-parity-followups
Aug 12, 2026
Merged

fix(uuid): unbreak compliance ratchet and match google/uuid leniency#196
sspaink merged 2 commits into
open-policy-agent:mainfrom
sspaink:fix/uuid-parity-followups

Conversation

@sspaink

@sspaink sspaink commented Aug 11, 2026

Copy link
Copy Markdown
Member

Two follow-ups to #155. First, uuid.parse/uuid.rfc4122 are registered in BuiltinRegistry but were left in known-missing-builtins.txt, so ComplianceTest currently fails on main with "listed ... but no compliance case reported them missing" — the first commit deletes the two lines.

Second, uuid.parse returned undefined for two forms OPA accepts, both checked with opa eval against OPA 1.19.0 (the version pinned in tools/generate-compliance-tests/go.mod): URN:UUID:... (google/uuid compares the prefix with strings.EqualFold) and the 38-byte form without literal braces such as (...) or X...Y (google/uuid strips the leading byte and only examines the middle 36). The upstream fixtures cover neither, so both get unit tests here; I'm proposing the cases to OPA so regenerate.sh picks them up later.

Two items from the review remain for follow-up: getEvaluationCacheValue reuses ctx.getNdCacheValues() (the decision-log reporting list) for same-key stability, and rfc4122 calls getArg purely for type validation while discarding the result.

uuid.parse and uuid.rfc4122 are registered in BuiltinRegistry as of
open-policy-agent#155, so no compliance case reports them missing anymore. The ratchet
fails on entries that are no longer missing, which leaves ComplianceTest
red on main:

  These builtins are listed in compliance/known-missing-builtins.txt but
  no compliance case reported them missing [...] [uuid.parse,
  uuid.rfc4122]

The four upstream uuid fixtures (9 cases) pass once the lines are gone.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
uuid.parse rejected two input forms that OPA accepts, both verified with
opa eval against OPA 1.19.0 (the version pinned by the compliance test
generator):

  uuid.parse("URN:UUID:000003e8-48b9-21ee-b200-325096b39f47")  # defined
  uuid.parse("(000003e8-48b9-21ee-b200-325096b39f47)")         # defined

google/uuid compares the urn prefix with strings.EqualFold, so any
casing parses; normalize() used a case-sensitive startsWith.

For the 38-byte "Microsoft style" form, google/uuid only strips the
first byte and then examines the middle 36 — indexes 0 and 37 are never
checked, as its doc comment notes ("Only the middle 36 bytes are
examined in the latter case"). normalize() required literal braces,
making (uuid), Xuuid Y and {uuidX undefined here but defined upstream.

The upstream uuid fixtures do not cover either case, so both get unit
tests until the cases can be contributed to OPA and picked up by
regenerate.sh.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
@sspaink
sspaink requested a review from a team as a code owner August 11, 2026 23:19
@sspaink
sspaink merged commit b8a71af into open-policy-agent:main Aug 12, 2026
20 checks passed
sspaink added a commit to sspaink/opa that referenced this pull request Aug 12, 2026
The existing uuid cases cover the lowercase urn form and the braced
38-byte form, but not two adjacent behaviors that fall out of
google/uuid.Parse:

  - the urn prefix is compared with strings.EqualFold, so URN:UUID: and
    any other casing parse just as urn:uuid: does — RFC 8141 makes the
    scheme and namespace identifier case-insensitive
  - the 38-byte "Microsoft style" form strips the leading byte and then
    examines only the middle 36, so the surrounding bytes need not be
    braces ("Only the middle 36 bytes are examined in the latter case")

Both are easy for a reimplementation to get wrong by reaching for a
case-sensitive prefix check or requiring literal braces, and neither is
currently pinned by a case. Both diverged in the Java SDK
(open-policy-agent/java-opa-sdk#196) while passing the existing
fixtures. Expected values were taken from OPA v1.19.0; per-case
rationale is in the fixture comments.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
sspaink added a commit to sspaink/opa that referenced this pull request Aug 12, 2026
The existing uuid cases cover the lowercase urn form and the braced
38-byte form, but not two adjacent behaviors that fall out of
google/uuid.Parse:

  - the urn prefix is compared with strings.EqualFold, so URN:UUID: and
    any other casing parse just as urn:uuid: does — RFC 8141 makes the
    scheme and namespace identifier case-insensitive
  - the 38-byte "Microsoft style" form strips the leading byte and then
    examines only the middle 36, so the surrounding bytes need not be
    braces ("Only the middle 36 bytes are examined in the latter case")

Both are easy for a reimplementation to get wrong by reaching for a
case-sensitive prefix check or requiring literal braces, and neither is
currently pinned by a case. Both diverged in the Java SDK
(open-policy-agent/java-opa-sdk#196) while passing the existing
fixtures. Expected values were taken from OPA v1.19.0; per-case
rationale is in the fixture comments.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
sspaink added a commit to sspaink/opa that referenced this pull request Aug 12, 2026
The existing uuid cases cover the lowercase urn form and the braced
38-byte form, but not two adjacent behaviors that fall out of
google/uuid.Parse:

  - the urn prefix is compared with strings.EqualFold, so URN:UUID: and
    any other casing parse just as urn:uuid: does — RFC 8141 makes the
    scheme and namespace identifier case-insensitive
  - the 38-byte "Microsoft style" form strips the leading byte and then
    examines only the middle 36, so the surrounding bytes need not be
    braces ("Only the middle 36 bytes are examined in the latter case")

Both are easy for a reimplementation to get wrong by reaching for a
case-sensitive prefix check or requiring literal braces, and neither is
currently pinned by a case. Both diverged in the Java SDK
(open-policy-agent/java-opa-sdk#196) while passing the existing
fixtures. Expected values were taken from OPA v1.19.0; per-case
rationale is in the fixture comments.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant